package ch.sv7.tool.dbmanager.db.xml;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import ch.sv7.tool.dbmanager.db.ColumnSchema;
import ch.sv7.tool.dbmanager.db.ColumnType;
import ch.sv7.tool.dbmanager.db.ConstraintSchema;
import ch.sv7.tool.dbmanager.db.DatabaseSchema;
import ch.sv7.tool.dbmanager.db.ForeignKeySchema;
import ch.sv7.tool.dbmanager.db.IndexSchema;
import ch.sv7.tool.dbmanager.db.TableSchema;
import ch.sv7.tool.xml.XMLDocumentWriter;

public class XmlDatabaseSchemaExport {

	public XmlDatabaseSchemaExport() {
	}

	public void exportToFile(String filename, DatabaseSchema ds) {
		try {
			exportToWriter(new PrintWriter(new FileOutputStream(filename)), ds);
		} catch (FileNotFoundException e) {
			System.out.println(e.getMessage() + filename);
		}
	}

	public void exportToWriter(PrintWriter printWriter, DatabaseSchema ds) {
		Document document = exportAsXml(ds);
		XMLDocumentWriter writer = new XMLDocumentWriter(printWriter);
		writer.write(document);
		writer.close();
	}

	public Document exportAsXml(DatabaseSchema ds) {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = null;
		try {
			builder = factory.newDocumentBuilder();
		} catch (ParserConfigurationException pce) {
			System.out.println(pce.getMessage());
			return null;
		}
		Document document = builder.newDocument();
		Element database = document.createElement("database");
		document.appendChild(database);
		Element table;
		for (Iterator iter = ds.iterator(); iter.hasNext(); database.appendChild(table)) {
			TableSchema ts = (TableSchema) iter.next();
			table = document.createElement("table");
			table.setAttribute("name", ts.getName());
			ColumnSchema cols[] = ts.getColumnSchemas();
			for (int i = 0; i < cols.length; i++) {
				ColumnSchema col = cols[i];
				Element column = document.createElement("column");
				column.setAttribute("name", col.getName());
				column.setAttribute("type", ColumnType.jdbcTypeToString(col.getType().getJDBCType()));
				column.setAttribute("size", Long.toString(col.getType().getSize()));
				if (col.getType().getDecimalSize() != 0){
					column.setAttribute("decimal-size", Long.toString(col.getType().getDecimalSize()));
				}
				column.setAttribute("nullable", col.getType().isNullable() ? "true" : "false");
				if (col.getType().getTypeName() != null){
					column.setAttribute("type-name", col.getType().getTypeName());
				}
				if (col.isPrimaryKey())
					column.setAttribute("key", "true");
				if (col.getType().getDefaultValue() != null){
					column.setAttribute("default-value", col.getType().getDefaultValue() == null ? "NULL" : col.getType().getDefaultValue());
				}
				table.appendChild(column);
			}
			List indexes = ts.getIndexes();
			for (int i=0; i<indexes.size(); i++) {
				IndexSchema index = (IndexSchema)indexes.get(i);
				Element ind = document.createElement("index");
				ind.setAttribute("name", index.getName());
				ind.setAttribute("qualifier", index.getQualifier());
				ind.setAttribute("type", index.getType());
				ind.setAttribute("columns", index.getColumns());
				ind.setAttribute("unique", Boolean.toString(index.isUnique()));
				ind.setAttribute("primary-key", Boolean.toString(index.isPrimaryKey()));
				table.appendChild(ind);
			}
			List foreignKeys = ts.getForeignKeys();
			for (int i=0; i<foreignKeys.size(); i++) {
				ForeignKeySchema fk = (ForeignKeySchema)foreignKeys.get(i);
				Element fkElt = document.createElement("foreign-key");
				fkElt.setAttribute("name", fk.getName());
				fkElt.setAttribute("columns", fk.getColumns());
				fkElt.setAttribute("foreign-table", fk.getForeignTable());
				fkElt.setAttribute("foreign-columns", fk.getForeignColumns());
				fkElt.setAttribute("update-rule", fk.getUpdateRule());
				fkElt.setAttribute("delete-rule", fk.getDeleteRule());
				fkElt.setAttribute("deferrability", fk.getDeferrability());
				table.appendChild(fkElt);
			}
			
			List constraints = ts.getConstraints();
			for (int i=0; i<constraints.size(); i++) {
				ConstraintSchema cs = (ConstraintSchema)constraints.get(i);
				Element csElt = document.createElement("constraint");
				csElt.setAttribute("name", cs.getName());
				csElt.setAttribute("definition", cs.getDefinition());
				table.appendChild(csElt);
			}

		}

		return document;
	}
}
